#pragma once
#include <tchar.h>

typedef System::String^ STRINGCS;
#define IN
#define OUT

STRINGCS UnmanagedString2ManagedString(TCHAR *pIn);
TCHAR* ManagedString2UnmanagedString(STRINGCS str);

char* toChar(const TCHAR* chars);

TCHAR* toWChar(char* cstr);

#define VALIDATE_NATIVE \
	if(!m_native) \
		return false;

#define ASSERTHANDLE(handle) \
	if(!handle) \
		return 0;

#define DECLARE_COLLECTION(thisClass,mem,memelname) \
	void Add(thisClass memelname); \
	bool Remove(int index); \
	property thisClass default[int]{ \
		thisClass get(int index) \
		{ \
			if(mem!=nullptr&&mem->Count>index) \
			{ \
			return mem[index]; \
			} \
			return nullptr; \
		} \
	} \
	property int Count{ \
		int get(){return mem->Count;} \
	}

#define IMPLEMENT_COLLECTION(thisClass,memClass,mem,memelname) \
	void thisClass::Add(memClass memelname) \
	{ \
		mem->Add(memelname); \
	} \
	bool thisClass::Remove(int index) \
	{ \
		if(mem->Count>index) \
		{ \
			mem->RemoveAt(index); \
			return true; \
		} \
		return false; \
	}
#define DECLAREREADONLYPROPERTY(type,name) \
	property type name;

#define SETREADONLYPROPERTY(type,name,value) \
	property type name{ \
		type get(){return value;} \
	}

#define IMPLEMENTREADONLYPROPERTY(thisClass,type,name,value) \
	property thisClass::type name{ \
		type get(){return value;} \
	}

#define SETWRITEONLYPROPERTY(type,name,value) \
	property type name{ \
		void set(type val) {value=val;} \
	}

#define CALL_NATIVE(thisClass,method) \
	thisClass* block=(thisClass*)m_handle; \
	return block->method();

#define CALL_NATIVE_ARG1(thisClass,method,arg1) \
	thisClass* block=(thisClass*)m_handle; \
	return block->method(arg1);

#define CALL_NATIVE_ARG2(thisClass,method,arg1,arg2) \
	thisClass* block=(thisClass*)m_handle; \
	return block->method(arg1,arg2);

#define CALL_NATIVE_ARG3(thisClass,method,arg1,arg2,arg3) \
	thisClass* block=(thisClass*)m_handle; \
	return block->method(arg1,arg2,arg3);

#define CALL_NATIVE_ARG4(thisClass,method,arg1,arg2,arg3,arg4) \
	thisClass* block=(thisClass*)m_handle; \
	return block->method(arg1,arg2,arg3,arg4);

#define CALL_NATIVE_NO_RET(thisClass,method) \
	thisClass* block=(thisClass*)m_handle; \
	block->method();

#define CALL_NATIVE_ARG1_NO_RET(thisClass,method,arg1) \
	thisClass* block=(thisClass*)m_handle; \
	block->method(arg1);

#define CALL_NATIVE_ARG2_NO_RET(thisClass,method,arg1,arg2) \
	thisClass* block=(thisClass*)m_handle; \
	block->method(arg1,arg2);

#define CALL_NATIVE_ARG3_NO_RET(thisClass,method,arg1,arg2,arg3) \
	thisClass* block=(thisClass*)m_handle; \
	block->method(arg1,arg2,arg3);

#define CALL_NATIVE_ARG4_NO_RET(thisClass,method,arg1,arg2,arg3,arg4) \
	thisClass* block=(thisClass*)m_handle; \
	block->method(arg1,arg2,arg3,arg4);

#define TYPES "void,bit,char,unsigned char,short,unsigned short,int,unsigned int,long,unsigned long,float,double,id type,string,opaque,signed char,long long,unsigned long long,__int64,unsigned __int64,variant,object,unicode string"

#define String2Char(str) \
	TCHAR* th=ManagedString2UnmanagedString(str); \
	char* fn=toChar(th);

#define DEF_NATIVE(thisClass,otherClass) \
private: \
	thisClass* m_native; \
internal: \
	property thisClass* Native{ \
		thisClass* get() {return m_native;} \
		void set(thisClass* value){ m_native=value;} \
	} \
	otherClass (thisClass* native) \
	{ \
		Native=native; \
	}
